package com.ccl.iot;

import com.ccl.iot.IOTObject.IOTScannableObject;
import com.ccl.iot.IOTObject.IOTScannableObject.IOTScanListener;

public class IOTScanner<TYPE> {
	public static final int KSCAN_TIME_OUT = 3000;

	public interface ScanImpl<TYPE> {
		public void scanStart();

		public TYPE scanFirst();

		public TYPE scanNext();

		public void scanDone();
	}

	private Object iScanLock = new Object();

	private IOTScannableObject<TYPE> iOwner = null;
	private volatile boolean iScanning = false;
	private int iScanCount = 0;

	public IOTScanner(IOTScannableObject<TYPE> aOwner) {
		iOwner = aOwner;
	}

	public boolean isScanning() {
		return iScanning;
	}

	public int getScanCount() {
		return iScanCount;
	}

	public boolean startScan(ScanImpl<TYPE> aScanImpl, IOTScanListener<TYPE> aListener) {
		if (aScanImpl != null) {
			synchronized (iScanLock) {
				if (iScanning == false) {
					iScanning = true;

					iScanCount++;
				} else {
					return false;
				}

				if (aListener != null) {
					aListener.onScanStart(iOwner);
				}

				aScanImpl.scanStart();

				{
					int tCount = 0;
					TYPE tResult;


						do {
							if (tCount == 0) {
								tResult = aScanImpl.scanFirst();
							} else {
								tResult = aScanImpl.scanNext();
							}

							if (tResult != null) {
								tCount++;

								if (aListener != null) {
									aListener.onScanResult(iOwner, tResult);
								}
							}
						} while (tResult != null && iScanning);
				}

			}
			
			aScanImpl.scanDone();
			
			iScanning = false;
			

			if (aListener != null) {
				aListener.onScanStop(iOwner);
			}

			synchronized (iScanLock) {
				iScanLock.notifyAll();
			}

			return true;
		}

		return false;
	}

	public boolean stopScan() {
		synchronized (iScanLock) {
			if (iScanning) {
				iScanning = false;
			} else {
				return false;
			}
		}

		synchronized (iScanLock) {
			try {
				iScanLock.wait(KSCAN_TIME_OUT);
			} catch (InterruptedException e) {
			}
		}

		return true;
	}

	public void reset() {
		stopScan();

		iScanCount = 0;
	}
}
